//Wrapper for EE::Chr
#pragma once
#include "stdafx.h"

namespace EsenthelNet
{
	///<summary>Character Action Type</summary>
	public enum class ActionType {
		///<summary>None</summary>
		ACTION_NONE    ,
		///<summary>Move to position</summary>
		ACTION_MOVE_TO ,
		///<summary>Move to direction</summary>
		ACTION_MOVE_DIR,
	};

	///<summary>Character Input</summary>
	public ref struct ChrInput {
	internal:
		ChrInput(EE::Game::ChrInput i) {
			input = new EE::Game::ChrInput();
			*input = i;
		}
		ChrInput(EE::Game::ChrInput* i) {
			input = i;
		}

		EE::Game::ChrInput* input;
	public:
		///<summary>If want to crouch</summary>
		Prop(bool, Crouch, input->crouch)
		///<summary>If want to walk</summary>
		Prop(bool, Walk, input->walk)
		///<summary>Dodge direction (-1, 0, +1)</summary>
		Prop(int, Dodge, input->dodge)
		///<summary>Jump velocity (0..Inf)</summary>
		Prop(float, Jump, input->jump)

		///<summary>Direction Vector</summary>
		PropVecP(Dir, input->dir)
		///<summary>Angle Vector</summary>
		PropVecP(Angle, input->angle)

	};

	///<summary>Game Character Object</summary>
	public ref class Chr : Obj{
	internal:
		Chr(EE::Game::Chr* c) {
			obj = c;
		}
	public:
		Chr() {
			obj = new EE::Game::Chr();
		}
		~Chr() { if(obj != NULL) delete obj; }

		///<summary>If in ready-stance, default=false</summary>
		Prop(bool, Ready, ((EE::Game::Chr*)obj)->ready)
		///<summary>If move through path by walking instead of running, default=false</summary>
		Prop(bool, MoveWalking, ((EE::Game::Chr*)obj)->move_walking)
		///<summary>Action type, default=ACTION_NONE</summary>
		PropTarget(EsenthelNet::ActionType, Action, ((EE::Game::Chr*)obj)->action, EE::Game::ACTION_TYPE)
		///<summary>Move speed, default= 4.1, for changing animations speed please check Chr::Animation::speed</summary>
		Prop(float, Speed, ((EE::Game::Chr*)obj)->speed)
		///<summary>Turn speed, default= 3.5</summary>
		Prop(float, TurnSpeed, ((EE::Game::Chr*)obj)->turn_speed)
		///<summary>Flying speed, default=25.0</summary>
		Prop(float, FlyingSpeed, ((EE::Game::Chr*)obj)->flying_speed)

		///<summary>Look angles</summary>
		PropVecP(Angle, ((EE::Game::Chr*)obj)->angle)
		///<summary>Overriding material</summary>
		PropMaterial(Material, ((EE::Game::Chr*)obj)->material)
		///<summary>Input</summary>
		property EsenthelNet::ChrInput^ Input { EsenthelNet::ChrInput^ get() { return gcnew EsenthelNet::ChrInput(&((EE::Game::Chr*)obj)->input); } void set(EsenthelNet::ChrInput^ value) { ((EE::Game::Chr*)obj)->input = *value->input; } }

		///<summary>Create from object parameters, if no Skeleton is given, it will be loaded from mesh file name (but with extension changed to ".skel"), Chr class accepts only Phys made from 1 Capsule (ignoring its 'up' vector), if no Phys is given the character controller will be created basing on the object scale</summary>
		virtual void Create(EsenthelNet::ObjParams^ params) override { ((EE::Game::Chr*)obj)->create(*params->params); }

		///<summary>Get/Set position</summary>
		property EsenthelNet::Vec^ Pos { virtual EsenthelNet::Vec^ get () override{ return gcnew EsenthelNet::Vec(&((EE::Game::Chr*)obj)->pos()); } virtual void set (EsenthelNet::Vec^ value) override{ ((EE::Game::Chr*)obj)->pos(*value->vec); }}
		///<summary>Get/Set matrix, only 'matrix.pos' is used in the set method</summary>
		property EsenthelNet::Matrix^ Matrix { virtual EsenthelNet::Matrix^ get () override{ return gcnew EsenthelNet::Matrix(&((EE::Game::Chr*)obj)->matrix()); } virtual void set (EsenthelNet::Matrix^ value) override{ ((EE::Game::Chr*)obj)->matrix(*value->matrix); }}

		///<summary>Break active action</summary>
		void ActionBreak() { ((EE::Game::Chr*)obj)->actionBreak(); }
		///<summary>Set action to move to position, false on fail</summary>
		bool ActionMoveTo(EsenthelNet::Vec^ pos) { return ((EE::Game::Chr*)obj)->actionMoveTo(*pos->vec); }
		///<summary>Set action to move to direction</summary>
		void ActionMoveDir(EsenthelNet::Vec^ dir) { ((EE::Game::Chr*)obj)->actionMoveDir(*dir->vec); }

		///<summary>Facial animation blending value, dependent on character visibility and distance from camera, returns value 0..1(0 disables facial animation), you can override this method and return your custom values</summary>
		virtual float AnimateFaceBlend() { return ((EE::Game::Chr*)obj)->animateFaceBlend(); }
		///<summary>If animate hand/foot fingers, dependent on character visibility and distance from camera, returns value true/false (false disables hands animation), you can override this method and return your custom values</summary>
		virtual bool AnimateFingers() { return ((EE::Game::Chr*)obj)->animateFingers(); }
		///<summary>How much to align feet on to the ground, returns value 0..1 (0  disables feet   aligning ), you can override this method and return your custom values</summary>
		virtual float AnimateAlignFeet() { return ((EE::Game::Chr*)obj)->animateAlignFeet(); }
		///<summary>This method is called when "step" event has occured in the most significant movement animation, you can override this method and for example play "step" sound</summary>
		virtual void AnimateStepOccured() { ((EE::Game::Chr*)obj)->animateStepOccured(); }

		///<summary>This method animates the character skeleton using default animations, it consists only of following : 'cskel.clear().animate(stand).animate(walk)...', you can override this method and use it in 2 ways: 1) use default animations and modify them - __super::animate(); cskel.animate(custom animation)... 2) use only custom animations -   cskel .clear  (); cskel.animate(custom animation)...</summary>
		virtual void Animate() { ((EE::Game::Chr*)obj)->animate(); }

		///<summary>This method is called when the skeleton is fully animated and is ready to have its matrixes updated, you can override this method and optionally modify the skeleton before or after calling the default 'animateUpdateMatrix' method</summary>
		virtual void AnimateUpdateMatrix(EsenthelNet::Matrix^ bodyMatrix) { ((EE::Game::Chr*)obj)->animateUpdateMatrix(*bodyMatrix->matrix); }


		///<summary>Call this at least once before manual operations on 'ragdoll' to make sure it has been properly initialized</summary>
		virtual void RagdollValidate() { ((EE::Game::Chr*)obj)->ragdollValidate(); }
		///<summary>Switch from skeleton animations to ragdoll  animations (RAGDOLL_FULL)</summary>
		virtual void RagdollEnable() { ((EE::Game::Chr*)obj)->ragdollEnable(); }
		///<summary>Switch from ragdoll  animations to skeleton animations (RAGDOLL_NONE)</summary>
		virtual void RagdollDisable() { ((EE::Game::Chr*)obj)->ragdollDisable(); }
		///<summary>Enable ragdoll blending for shot/hit simulation (RAGDOLL_PART), if current 'ragdoll_mode' is set to RAGDOLL_FULL then the call will fail and false will be returned</summary>
		virtual bool RagdollBlend() { return ((EE::Game::Chr*)obj)->ragdollBlend(); }

		///<summary>Update, return false when object wants to be deleted, and true if wants to exist</summary>
		virtual bool Update() override { return ((EE::Game::Chr*)obj)->update(); }

		///<summary>Prepare for drawing, this will be called in RM_PREPARE mode, in this method you should add the meshes to the draw list (Mesh::draw), and return a combination of bits of which additional render modes will be required for custom drawing of the object (for example "return IndexToFlag(RM_BLEND)" requests blend mode rendering)</summary>
		virtual unsigned int DrawPrepare() override { return ((EE::Game::Chr*)obj)->drawPrepare(); }
		///<summary>In this method you should add the meshes to the shadow draw list (Mesh::drawShadow)</summary>
		virtual void DrawShadow() { ((EE::Game::Chr*)obj)->drawShadow(); }

		///<summary>Enable object when closes in, here all dynamic actors should disable kinematic flag - actor.kinematic(false), this is called when an object changes its state to AREA_ACTIVE</summary>
		virtual void Enable() override { ((EE::Game::Chr*)obj)->enable(); }
		///<summary>Disable object when becomes too far away, here all dynamic actors should  enable kinematic flag - actor.kinematic(true ), this is called when an object changes its state to AREA_INACTIVE</summary>
		virtual void Disable() override { ((EE::Game::Chr*)obj)->disable(); }


	};
}
